﻿using DDitApplicationFrame.Common;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace DDit.Component.Tools.weixin
{
    public class WxUserManage
    {
        private static string appID = "wxcbe7abc57ddd67a4";
        private static string appsecret = "c38e97122bcf08722b83007633582c10";
        private static string key_access_token = "wxAccessToken";
        private static string key_expires_in = "wxCreateTime";
        private static string key_user_tag = "usertag";
        /// <summary>
        /// 验证微信签名
        /// </summary>
        public static bool CheckSignature(string token, string signature, string timestamp, string nonce)
        {
            string[] ArrTmp = { token, timestamp, nonce };

            Array.Sort(ArrTmp);
            string tmpStr = string.Join("", ArrTmp);
            var data = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(tmpStr));
            var sb = new StringBuilder();
            foreach (var t in data)
            {
                sb.Append(t.ToString("X2"));
            }
            tmpStr = sb.ToString();
            tmpStr = tmpStr.ToLower();

            if (tmpStr == signature)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 获取Token
        /// </summary>
        /// <returns></returns>
        public static string Token
        {
            get
            {
                //return "zU0GjsXjOsa48NI_XTPjZ9eoRm9BqSflvvMKLEDR6HwB-cNl2zcOIoH9brvKdcAXHwubVcNYMTsHJ7xmza6eCVdLj42MW_xgBjhXE2NHoGtNeVDolCevBb5m8DDd_uQwTWVhAEAORQ";

                string tempToken = CacheHelp.GetCache(key_access_token) as string;
                string ctreatTime = CacheHelp.GetCache(key_expires_in) as string;
                int cTime = 0;
                int.TryParse(ctreatTime, out cTime);
                TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1);
                if (cTime < ts.TotalSeconds)
                {
                    string url = string.Format(WxApiUrl.Token, appID, appsecret);
                    var rel = HttpHelper.HttpGet(url, "");
                    var jsn = JsonConvert.DeserializeObject<dynamic>(rel);
                    tempToken = jsn.access_token;
                    ctreatTime = jsn.expires_in;

                    cTime = (int)ts.TotalSeconds + int.Parse(ctreatTime);

                    CacheHelp.SetCache(key_access_token, tempToken, DateTime.Now.AddHours(12));
                    CacheHelp.SetCache(key_expires_in, cTime.ToString(), DateTime.Now.AddHours(12));
                }

                return tempToken;


            }
        }
        /// <summary>
        /// 处理接收到的消息
        /// </summary>
        /// <param name="content"></param>
        /// <returns></returns>
        public static string Rev(string content)
        {
            RevMessage msg;
            using (StringReader sr = new StringReader(content))
            {
                XmlSerializer xmldes = new XmlSerializer(typeof(RevMessage));
                msg = xmldes.Deserialize(sr) as RevMessage;
            }
            string strResult = "";
            if (msg != null)
            {
                switch (msg.MsgType)
                {
                    case "text":
                        strResult = WxApiUrl.ConnectTuLing(msg.Content);
                        strResult = SendTemplate.SendText(msg.FromUserName, msg.ToUserName, strResult);
                        break;
                    case "image":
                        break;
                    default:
                        break;
                }
            }
            return strResult;
        }

        public static List<WxUser> UserListTest()
        {
            string userList = "{\"user_info_list\":[{\"subscribe\":1,\"openid\":\"oInXojnaJsWNfrzZRP-DnQYtaGvs\",\"nickname\":\"宸语\",\"sex\":1,\"language\":\"zh_CN\",\"city\":\"郑州\",\"province\":\"河南\",\"country\":\"中国\",\"headimgurl\":\"http://wx.qlogo.cn/mmopen/OW13h8v0mU2LGWTQdo9s0XRMNgXpvE7k2Xa0sTIdMuh5wrib6xSN3vBIIwu540W3W4dbaHOSWQvG2ibngKrzn6aOS2I21mCt4I/0\",\"subscribe_time\":1413773727,\"remark\":\"\",\"groupid\":0,\"tagid_list\":[]},{\"subscribe\":1,\"openid\":\"oInXojpvlTuIWcGUWYHmIewdPAbg\",\"nickname\":\"小小语\",\"sex\":2,\"language\":\"zh_CN\",\"city\":\"郑州\",\"province\":\"河南\",\"country\":\"中国\",\"headimgurl\":\"http://wx.qlogo.cn/mmopen/OW13h8v0mU2LGWTQdo9s0XH5LJFF6aUcTL2cs6CXOFicibwX16m3lgmo7mAowpCknSiaUabXWgdKHynD0iccNEYv6MWBWMEudxIH/0\",\"subscribe_time\":1495197442,\"remark\":\"\",\"groupid\":0,\"tagid_list\":[]}]}";
            JObject ResultJson = JsonConvert.DeserializeObject<JObject>(userList);
            var data = ResultJson.GetValue("user_info_list").ToString();
            return JsonConvert.DeserializeObject<List<WxUser>>(data);
        }

        /// <summary>
        /// 获取用户信息
        /// </summary>
        /// <param name="page">第几页  从0开始</param>
        /// <param name="pagesize">每页数量</param>
        /// <returns></returns>
        public static List<WxUser> GetUserList(int star, int pagesize, ref int Total)
        {
            ArrayList arr = new ArrayList();
            string next_token = "";
            string url = "";
            JObject ResultJson;
            while (true)
            {
                url = string.Format(WxApiUrl.UserList, Token, next_token);
                ResultJson = JsonConvert.DeserializeObject<JObject>(HttpHelper.HttpGet(url, ""));
                VerifyErrorCode(ResultJson.ToString());
                Total = ResultJson.Value<int>("total");
                int nSel = ResultJson.Value<int>("count");
                if (nSel == 0)
                    break;
                next_token = ResultJson.Value<string>("next_openid");
                var reldata = ResultJson.GetValue("data").Value<JArray>("openid").Values<string>();
                arr.AddRange(reldata.ToArray());
            }

            List<string> openids = new List<string>();
            for (int i = star; i < star + pagesize; i++)
            {
                if (i == arr.Count)
                {
                    break;
                }
                openids.Add(arr[i].ToString());
            }
            return GetListUserInfo(openids);
        }
        /// <summary>
        /// 设置用户备注名
        /// </summary>
        /// <param name="openid"></param>
        /// <param name="remark"></param>
        public static void SetRemark(string openid, string remark)
        {
            string postval = "{\"openid\":\"" + openid + "\",\"remark\":\"" + remark + "\"}";
            string url = string.Format(WxApiUrl.RemarkInfo, Token);
            string rel = HttpHelper.HttpPost(url, postval);
            JObject ResultJson = JsonConvert.DeserializeObject<JObject>(rel);
            VerifyErrorCode(ResultJson.ToString());
        }
        #region 黑名单
        /// <summary>
        ///  拉黑用户
        /// </summary>
        /// <param name="openids"></param>
        public static void PullBlack(List<string> openids)
        {
            if (openids.Count == 0) return;
            string postval = "{\"opened_list\":[";
            foreach (var id in openids)
            {
                postval += "\"" + id + "\",";
            }
            postval = postval.Substring(0, postval.Length - 1);
            postval += "]}";
            string url = string.Format(WxApiUrl.PullBlackUser, Token);
            string rel = HttpHelper.HttpPost(url, postval);
            JObject ResultJson = JsonConvert.DeserializeObject<JObject>(rel);
            VerifyErrorCode(ResultJson.ToString());
        }
        /// <summary>
        /// 取消拉黑用户
        /// </summary>
        /// <param name="openids"></param>
        public static void CancelBlack(List<string> openids)
        {
            if (openids.Count == 0) return;
            string postval = "{\"opened_list\":[";
            foreach (var id in openids)
            {
                postval += "\"" + id + "\",";
            }
            postval = postval.Substring(0, postval.Length - 1);
            postval += "]}";
            string url = string.Format(WxApiUrl.CancelBlack, Token);
            string rel = HttpHelper.HttpPost(url, postval);
            JObject ResultJson = JsonConvert.DeserializeObject<JObject>(rel);
            VerifyErrorCode(ResultJson.ToString());
        }
        /// <summary>
        /// 获取公众号的黑名单列表
        /// </summary>
        /// <param name="star"></param>
        /// <param name="pagesize"></param>
        /// <param name="Total"></param>
        public static List<WxUser> GetBlackUser(int star, int pagesize, ref int Total)
        {
            ArrayList arr = new ArrayList();
            string next_token = "";
            string url = "";
            JObject ResultJson;

            while (true)
            {
                string postval = "{\"begin_openid\":\"" + next_token + "\"}";
                url = string.Format(WxApiUrl.GetBlackUser, Token);
                ResultJson = JsonConvert.DeserializeObject<JObject>(HttpHelper.HttpPost(url, postval));
                VerifyErrorCode(ResultJson.ToString());
                Total = ResultJson.Value<int>("total");
                int nSel = ResultJson.Value<int>("count");
                if (nSel == 0)
                    break;
                next_token = ResultJson.Value<string>("next_openid");
                var reldata = ResultJson.GetValue("data").Value<JArray>("openid").Values<string>();
                arr.AddRange(reldata.ToArray());
            }

            List<string> openids = new List<string>();
            for (int i = star; i < star + pagesize; i++)
            {
                if (i == arr.Count)
                {
                    break;
                }
                openids.Add(arr[i].ToString());
            }
            return GetListUserInfo(openids);
        }
        #endregion

        #region tag
        /// <summary>
        /// 创建和修改标签
        /// </summary>
        /// <param name="id"></param>
        /// <param name="name"></param>
        public static void SetTag(int id, string name)
        {
            string postval = "";
            string url = "";
            if (id == 0)
            {
                postval = "{ \"tag\" : {\"name\":\"" + name + "\"}";
                url = string.Format(WxApiUrl.createTag, Token);
            }
            else
            {
                postval = "{ \"tag\" : { \"id\":" + id + ", \"name\":\"" + name + "\"}";
                url = string.Format(WxApiUrl.updateTag, Token);
            }
            string rel = HttpHelper.HttpPost(url, postval);
            JObject ResultJson = JsonConvert.DeserializeObject<JObject>(rel);
            VerifyErrorCode(ResultJson.ToString());
            CacheHelp.RemoveKeyCache(key_user_tag);
        }
        /// <summary>
        /// 删除标签
        /// </summary>
        /// <param name="id"></param>
        public static void DelTag(int id)
        {
            string postval = "";
            string url = "";
            postval = "{ \"tag\" : { \"id\":" + id + "\"}";
            url = string.Format(WxApiUrl.deleteTag, Token);

            string rel = HttpHelper.HttpPost(url, postval);
            JObject ResultJson = JsonConvert.DeserializeObject<JObject>(rel);
            VerifyErrorCode(ResultJson.ToString());
            CacheHelp.RemoveKeyCache(key_user_tag);
        }
        /// <summary>
        /// 获取所有标签
        /// </summary>
        /// <param name="reload"></param>
        /// <returns></returns>
        public static List<WxGroup> GetGroup(bool reload)
        {
            List<WxGroup> lstGroup = new List<WxGroup>();
            if (!reload)
            {
                lstGroup = CacheHelp.GetCache(key_user_tag) as List<WxGroup>;
                if (lstGroup != null)
                    return lstGroup;
                else
                    lstGroup = new List<WxGroup>();
            }

            string url = string.Format(WxApiUrl.getTag, Token);

            var ResultJson = JsonConvert.DeserializeObject<JObject>(HttpHelper.HttpGet(url, ""));
            VerifyErrorCode(ResultJson.ToString());
            var data = ResultJson.GetValue("tags").ToString();
            lstGroup = JsonConvert.DeserializeObject<List<WxGroup>>(data);
            CacheHelp.SetCache(key_user_tag, lstGroup, DateTime.Now.AddHours(12));
            return lstGroup;

        }
        /// <summary>
        /// 批量为用户取消标签
        /// </summary>
        /// <param name="ids"></param>
        /// <param name="tagid"></param>
        /// <param name="add"></param>
        public static void SetUerTag(List<string> ids, int tagid, bool add)
        {
            StringBuilder str = new StringBuilder();
            str.Append("{\"openid_list\" : [");
            foreach (var openid in ids)
            {
                str.Append("\"");
                str.Append(openid);
                str.Append("\",");
            }
            str.Remove(str.Length - 1, 1);
            str.Append("], \"tagid\" : ");
            str.Append(tagid);
            str.AppendLine("}");


            string url;
            if (add)
                url = string.Format(WxApiUrl.addUserTage, Token);
            else
                url = string.Format(WxApiUrl.delUserTage, Token);
            var ResultJson = JsonConvert.DeserializeObject<JObject>(HttpHelper.HttpPost(url, str.ToString()));
            VerifyErrorCode(ResultJson.ToString());
        }
        /// <summary>
        /// 获取用户组下用户信息
        /// </summary>
        /// <param name="tagid"></param>
        /// <param name="star"></param>
        /// <param name="pagesize"></param>
        /// <param name="Total"></param>
        /// <returns></returns>
        public static List<WxUser> GetTagUserList(int tagid, int star, int pagesize, ref int Total)
        {
            ArrayList arr = new ArrayList();
            string next_token = "";
            string url = "";
            string postval = "";
            JObject ResultJson;
            while (true)
            {
                url = string.Format(WxApiUrl.GetTageUser, Token);
                postval = "{ \"tagid\" : " + tagid + ",";
                if (!string.IsNullOrEmpty(next_token))
                {
                    postval += " \"next_openid\":\"" + next_token + "\"";
                }
                postval += "}";
                ResultJson = JsonConvert.DeserializeObject<JObject>(HttpHelper.HttpPost(url, postval));
                VerifyErrorCode(ResultJson.ToString());
                int nSel = ResultJson.Value<int>("count");
                if (nSel == 0)
                    break;
                Total += nSel;
                next_token = ResultJson.Value<string>("next_openid");
                var reldata = ResultJson.GetValue("data").Value<JArray>("openid").Values<string>();
                arr.AddRange(reldata.ToArray());
            }
            List<string> openids = new List<string>();
            for (int i = star; i < star + pagesize; i++)
            {
                if (i == arr.Count)
                {
                    break;
                }
                openids.Add(arr[i].ToString());
            }
            return GetListUserInfo(openids);
        }
        #endregion
        /// <summary>
        /// 获取用户详细信息
        /// </summary>
        /// <param name="openids"></param>
        /// <returns></returns>
        public static List<WxUser> GetListUserInfo(List<string> openids)
        {
            if (openids.Count == 0)
                return new List<WxUser>();
            List<WxUser> lst = new List<WxUser>();
            string postval = "{\"user_list\": [";
            foreach (var opendid in openids)
            {
                postval += "{ \"openid\": \"" + opendid + "\",\"lang\": \"zh_CN\"},";
            }
            postval = postval.Substring(0, postval.Length - 1);
            postval += "]}";

            string url = string.Format(WxApiUrl.UserInfoList, Token);
            JObject ResultJson = JsonConvert.DeserializeObject<JObject>(HttpHelper.HttpPost(url, postval));
            VerifyErrorCode(ResultJson.ToString());
            var data = ResultJson.GetValue("user_info_list").ToString();
            lst = JsonConvert.DeserializeObject<List<WxUser>>(data);

            return lst;
        }
        /// <summary>  
        /// 反序列化  
        /// </summary>  
        /// <param name="type">类型</param>  
        /// <param name="xml">XML字符串</param>  
        /// <returns></returns>  
        private object Deserialize(Type type, string xml)
        {
            using (StringReader sr = new StringReader(xml))
            {
                XmlSerializer xmldes = new XmlSerializer(type);
                return xmldes.Deserialize(sr);
            }
        }

        /// <summary>
        /// 检查返回的记录，如果返回没有错误，或者结果提示成功，则不抛出异常
        /// </summary>
        /// <param name="content">返回的结果</param>
        /// <returns></returns>
        private static void VerifyErrorCode(string content)
        {
            if (content.Contains("errcode"))
            {
                ResultError errorResult = JsonConvert.DeserializeObject<ResultError>(content);
                //非成功操作才记录异常，因为有些操作是返回正常的结果（{"errcode": 0, "errmsg": "ok"}）
                if (errorResult != null && errorResult.errcode != 0)
                {
                    string strError = string.Format("微信请求发生错误！错误代码：{0}，说明：{1}", errorResult.errcode, errorResult.errmsg);
                    throw new Exception(strError);
                }
            }
        }
    }
}
